package cn.ltpcloud.admin.web.service.impl;

import cn.ltpcloud.admin.web.service.SystemMenuService;
import cn.ltpcloud.common.entity.AjaxResult;
import cn.ltpcloud.common.pojo.mapper.SysMenuMapper;
import cn.ltpcloud.common.pojo.mapper.SysRoleMenuMapper;
import cn.ltpcloud.common.pojo.mapper.SysUserMapper;
import cn.ltpcloud.common.pojo.po.SysMenu;
import cn.ltpcloud.common.pojo.po.SysRoleMenu;
import com.baomidou.dynamic.datasource.annotation.Slave;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validator;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import static cn.ltpcloud.common.utils.GenerateUtils.menuTree;
import static cn.ltpcloud.common.utils.ReqUtils.getUserId;

/**
 * @author jiejiebiezheyang
 * @since 2024-07-03 22:00
 */
@Service
@Transactional
public class SystemMenuServiceImpl implements SystemMenuService {

    @Resource
    private Validator validator;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;
    @Resource
    private SysMenuMapper sysMenuMapper;


    /**
     * 当前用户菜单
     */
    @Override
    public AjaxResult userMenu() {
        Integer userId = getUserId();
        Set<String> sysRoles = sysUserMapper.selectUserAllRole(userId);
        boolean hasSuper = sysRoles.contains("super");
        // 用户菜单
        List<SysMenu> menus;
        if (hasSuper) {
            // 超级管理员所有菜单
            menus = sysUserMapper.selectAllMenu();
        } else {
            // 其他用户菜单
            menus = sysUserMapper.selectUserAllMenu(userId);
        }
        List<SysMenu> pMenus = menuTree(menus);
        return AjaxResult.success(pMenus);
    }

    /**
     * 菜单列表
     */
    @Override
    public AjaxResult topMenuList() {
        List<SysMenu> menus = sysUserMapper.selectAllMenu();
        // 树形结构
        List<SysMenu> pMenus = menuTree(menus);
        return AjaxResult.success(pMenus);
    }

    /**
     * 添加菜单
     */
    @Override
    public AjaxResult addMenu(@RequestBody SysMenu sysMenu) {
        if ("M".equals(sysMenu.getMenuType())) {
            // 二级菜单校验
            Set<ConstraintViolation<SysMenu>> set = validator.validate(sysMenu, SysMenu.CreateSecond.class);
            if (!set.isEmpty()) {
                List<String> errorList = set.stream().map(ConstraintViolation::getMessage).toList();
                return AjaxResult.error("数据校验失败", errorList);
            }
        }
        String type = sysMenu.getMenuType();
        if ("D".equalsIgnoreCase(type) || "B".equalsIgnoreCase(type)) {
            // 目录和按钮将组件路径设置为 null
            sysMenu.setComponentPath(null);
        }
        sysMenu.setId(null);
        sysMenu.setCreateBy(getUserId());
        sysMenu.setCreateTime(new Date());
        sysMenu.setUpdateBy(getUserId());
        sysMenu.setUpdateTime(new Date());
        sysMenuMapper.insert(sysMenu);
        return AjaxResult.success();
    }

    /**
     * 更新菜单
     */
    @Override
    public AjaxResult updateMenu(SysMenu sysMenu) {
        if ("M".equals(sysMenu.getMenuType())) {
            // 二级菜单校验
            Set<ConstraintViolation<SysMenu>> set = validator.validate(sysMenu, SysMenu.CreateSecond.class);
            if (!set.isEmpty()) {
                List<String> errorList = set.stream().map(ConstraintViolation::getMessage).toList();
                return AjaxResult.error("数据校验失败", errorList);
            }
        }
        sysMenu.setUpdateBy(getUserId());
        sysMenu.setUpdateTime(new Date());
        sysMenuMapper.updateById(sysMenu);
        return AjaxResult.success();
    }

    /**
     * 删除菜单
     */
    @Override
    public AjaxResult deleteMenu(Integer id) {
        SysMenu one = sysMenuMapper.selectById(id);
        String type = one.getMenuType();
        if ("B".equalsIgnoreCase(type)) {
            // 是 按钮 直接删除
            sysMenuMapper.deleteById(id);
            return AjaxResult.success();
        }
        //  需要删除的id
        List<Integer> ids = new ArrayList<>();
        // 将id添加到待删除的id集合
        ids.add(id);
        QueryWrapper<SysMenu> queryChildren = new QueryWrapper<>();
        queryChildren.eq("parent_id", id);
        // 子菜单或按钮的id
        List<Integer> childrenIds = sysMenuMapper.selectList(queryChildren)
                .stream()
                .map(SysMenu::getId)
                .toList();
        ids.addAll(childrenIds);
        if ("D".equalsIgnoreCase(type)) {
            // 如果是 目录, 代表上面获取的为 二级菜单
            // 需要再 获取 二级菜单 的 权限按钮
            queryChildren = new QueryWrapper<>();
            queryChildren.in("parent_id", ids);
            childrenIds = sysMenuMapper.selectList(queryChildren)
                    .stream()
                    .map(SysMenu::getId)
                    .toList();
            ids.addAll(childrenIds);
        }
        // 先删除 关联
        QueryWrapper<SysRoleMenu> wrapper = new QueryWrapper<>();
        wrapper.in("menu_id", ids);
        sysRoleMenuMapper.delete(wrapper);
        // 删除菜单
        sysMenuMapper.deleteBatchIds(ids);
        return AjaxResult.success();
    }

    /**
     * 权限列表
     */
    @Override
    public AjaxResult permList(Integer id) {
        QueryWrapper<SysMenu> wrapper = new QueryWrapper<>();
        wrapper.eq("menu_type", "B").eq("parent_id", id);
        List<SysMenu> perms = sysMenuMapper.selectList(wrapper);
        return AjaxResult.success(perms);
    }

    /**
     * 添加权限
     */
    @Override
    public AjaxResult addPerm(SysMenu sysMenu) {
        SysMenu one = new SysMenu();
        one.setPermission(sysMenu.getPermission());
        one.setMenuName(sysMenu.getMenuName());
        one.setParentId(sysMenu.getParentId());
        one.setMenuType("B");
        one.setCreateBy(getUserId());
        one.setCreateTime(new Date());
        one.setUpdateBy(getUserId());
        one.setUpdateTime(new Date());
        one.setSort(1);
        sysMenuMapper.insert(one);
        return AjaxResult.success();
    }

    /**
     * 更新权限
     */
    @Override
    public AjaxResult updatePerm(SysMenu sysMenu) {
        sysMenu.setUpdateBy(getUserId());
        sysMenu.setUpdateTime(new Date());
        sysMenuMapper.updateById(sysMenu);
        return AjaxResult.success();
    }

    /**
     * 菜单图标
     */
    @Override
    public AjaxResult icons() {
        List<SysMenu> icons = sysMenuMapper.selectIcons();
        return AjaxResult.success(icons);
    }
}
